const TAFFY = require('./taffy');
const LocalStorage = require('node-localstorage').LocalStorage;
const fs = require('fs');
function db(dbFileBasePath){
    const localStorage = new LocalStorage(dbFileBasePath+'dbf');

    const dateFormat = /^\d{4}-\d{2}-\d{2}(T|[\s])\d{2}:\d{2}:\d{2}(\.\d{3})?Z?$/;
    const sdateFormat = /^(\d{4})-(\d{2})-(\d{2})([\s])(\d{2}):(\d{2}):(\d{2})$/;
    function reviver(key, value) {
        if (typeof value === "string" && sdateFormat.test(value)) {
            let nvalue = value.replace(/\s/,'T')+'.000Z';
            let nd = new Date(nvalue);
            // console.log("dateValue:"+value+"   nvalue:"+nvalue+"  ndate:"+nd);
            // console.log(nd);
            return nd;
        }
        if (typeof value === "string" && dateFormat.test(value)) {
            let nd = new Date(value);
            // console.log("dateValue:"+value+"  ndate:"+nd);
            // console.log(nd);
            return nd;
        }
        return value;
    }

    function saveToFile(str){
        let path=dbFileBasePath,filename="data.indx";
        fs.writeFile(path+filename,str, (err)=>{
            if(err){
                console.log(err);
            }
        });
        // fs.close();
    }
    function checkTable(self,name){
        if(!self.tbs[name]){
            self.tbs[name] = TAFFY.taffy([]);
        }
        if(!self.tbns.includes(name)){
            self.tbns.push(name);
            saveToFile(self.tbns.join(","));
        }
    }
    function storeData(self,name){
        let ttb = self.tbs[name];
        ttb = ttb();
        let cs = ttb.get();
        localStorage.setItem(name,JSON.stringify(cs));
    }
    class Database {
        constructor() {
            this.tbns = [];
            this.tbs={};
            let path=dbFileBasePath,filename="data.indx";
            !fs.existsSync(path) && fs.mkdirSync(path, { recursive: true });
            try {
                if(fs.existsSync(path+filename)){
                    var data = fs.readFileSync(path+filename, 'utf8');
                    let content = data.toString();
                    // fs.close();
                    this.tbns = content.split(",");
                    for(var i=0;i<this.tbns.length;i++){
                        let tb = localStorage.getItem(this.tbns[i]);
                        if(tb){
                            this.tbs[this.tbns[i]] = TAFFY.taffy(JSON.parse(tb, reviver));
                        }
                    }
                    console.log(content);
                }
            } catch(e) {
                console.log('Error:', e.stack);
            }
        }
        table (name){
            checkTable(this,name);
            return this.tbs[name];
        };
        insert (name,data){
            checkTable(this,name);
            // else{
            let tb = this.tbs[name];
            let rst = tb.insert(data);

            storeData(this,name);

            return rst.get();
            // }
        };
        merge (name,data,key){
            checkTable(this,name);
            // else{
            let tb = this.tbs[name];
            let rst = tb.merge(data,key);

            storeData(this,name);

            return rst.get();
            // }
        };
        list (name,limit,page,conditions,sort,joins){
            checkTable(this,name);
            let tb = this.tbs[name];
            tb = tb();
            if(limit){
                tb = tb.limit(limit);
            }
            if(page){
                tb = tb.start(page);
            }
            if(sort){
                tb.order(sort);
            }
            let rst;
            if(conditions){
                tb = tb.filter(conditions);
            }
            rst = tb.get();
            return rst;
        };
        update (name,conditions,columns){
            checkTable(this,name);
            let tb = this.tbs[name];
            tb = tb();
            if(conditions){
                tb = tb.filter(conditions);
            }
            if(columns){
                tb = tb.update(columns);
            }
            let rst = tb.get();

            storeData(this,name);

            return rst;
        };
        delete (name,conditions){
            checkTable(this,name);
            let tb = this.tbs[name];
            tb = tb();
            if(conditions){
                tb = tb.filter(conditions);
            }
            let rst = tb.remove();
            storeData(this,name);

            return rst;
        };
    }


    return new Database();
}
module.exports = db;
